use std::error::Error;
use std::fs;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use tokio::sync::RwLock;
use notify::{Watcher, RecursiveMode, Event};
use serde::{Deserialize, Serialize};
use log::{error, warn, info};

use super::data_source_config::{DataSourceConfig, MultiDataSourceConfig};
use crate::data::source::{self, DataSource};
use crate::data::market_data_collector::MarketDataCollector;
use crate::data::source::health_check::HealthChecker;

#[derive(Debug)]
pub enum ConfigError {
    FileError(std::io::Error),
    ParseError(serde_yaml::Error),
    WatchError(notify::Error),
    InvalidConfig(String),
}

impl std::fmt::Display for ConfigError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ConfigError::FileError(e) => write!(f, "File error: {}", e),
            ConfigError::ParseError(e) => write!(f, "Parse error: {}", e),
            ConfigError::WatchError(e) => write!(f, "Watch error: {}", e),
            ConfigError::InvalidConfig(msg) => write!(f, "Invalid configuration: {}", msg),
        }
    }
}

impl Error for ConfigError {}

pub struct ConfigManager {
    config_path: PathBuf,
    current_config: Arc<RwLock<MultiDataSourceConfig>>,
    collector: Arc<RwLock<MarketDataCollector>>,
    health_checkers: Arc<RwLock<Vec<HealthChecker>>>,
}

impl ConfigManager {
    pub async fn new<P: AsRef<Path>>(config_path: P) -> Result<Self, ConfigError> {
        let config_path = config_path.as_ref().to_path_buf();
        let config = Self::load_config(&config_path)?;
        let collector = Self::create_collector(&config).await?;
        let health_checkers = Self::create_health_checkers(&collector).await;

        let manager = Self {
            config_path,
            current_config: Arc::new(RwLock::new(config)),
            collector: Arc::new(RwLock::new(collector)),
            health_checkers: Arc::new(RwLock::new(health_checkers)),
        };

        manager.start_watching()?;
        Ok(manager)
    }

    fn load_config(path: &Path) -> Result<MultiDataSourceConfig, ConfigError> {
        let content = fs::read_to_string(path)
            .map_err(ConfigError::FileError)?;
        serde_yaml::from_str(&content)
            .map_err(ConfigError::ParseError)
    }

    async fn create_collector(config: &MultiDataSourceConfig) -> Result<MarketDataCollector, ConfigError> {
        let primary_source = source::create_data_source(&config.primary);
        
        let mut backup_sources = Vec::new();
        for backup_config in &config.backups {
            backup_sources.push(source::create_data_source(backup_config));
        }

        Ok(MarketDataCollector::new(
            primary_source,
            backup_sources,
            config.primary.clone(),
        ))
    }

    async fn create_health_checkers(collector: &MarketDataCollector) -> Vec<HealthChecker> {
        let mut checkers = Vec::new();
        
        // 为主数据源创建健康检查器
        let primary_checker = HealthChecker::new(
            Arc::new(collector.get_primary_source().await),
            std::time::Duration::from_secs(60),
            3,
        );
        primary_checker.start_monitoring().await;
        checkers.push(primary_checker);

        // 为每个备用数据源创建健康检查器
        for source in collector.get_backup_sources().await {
            let checker = HealthChecker::new(
                Arc::new(source),
                std::time::Duration::from_secs(60),
                3,
            );
            checker.start_monitoring().await;
            checkers.push(checker);
        }

        checkers
    }

    fn start_watching(&self) -> Result<(), ConfigError> {
        let config_path = self.config_path.clone();
        let current_config = self.current_config.clone();
        let collector = self.collector.clone();
        let health_checkers = self.health_checkers.clone();

        let (tx, rx) = std::sync::mpsc::channel();
        let mut watcher = notify::recommended_watcher(tx)
            .map_err(ConfigError::WatchError)?;

        watcher.watch(&config_path, RecursiveMode::NonRecursive)
            .map_err(ConfigError::WatchError)?;

        tokio::spawn(async move {
            for res in rx {
                match res {
                    Ok(Event { kind: notify::EventKind::Modify(_), .. }) => {
                        if let Err(e) = Self::handle_config_change(
                            &config_path,
                            &current_config,
                            &collector,
                            &health_checkers
                        ).await {
                            error!("Failed to handle configuration change: {}", e);
                        }
                    }
                    Err(e) => error!("Watch error: {}", e),
                    _ => {}
                }
            }
        });

        Ok(())
    }

    async fn handle_config_change(
        config_path: &Path,
        current_config: &RwLock<MultiDataSourceConfig>,
        collector: &RwLock<MarketDataCollector>,
        health_checkers: &RwLock<Vec<HealthChecker>>,
    ) -> Result<(), ConfigError> {
        // 加载新配置
        let new_config = Self::load_config(config_path)?;

        // 验证新配置
        Self::validate_config(&new_config)?;

        // 创建新的数据采集器
        let new_collector = Self::create_collector(&new_config).await?;

        // 创建新的健康检查器
        let new_health_checkers = Self::create_health_checkers(&new_collector).await;

        // 更新配置和组件
        {
            let mut config = current_config.write().await;
            let mut col = collector.write().await;
            let mut checkers = health_checkers.write().await;

            *config = new_config;
            *col = new_collector;
            *checkers = new_health_checkers;
        }

        info!("Configuration updated successfully");
        Ok(())
    }

    fn validate_config(config: &MultiDataSourceConfig) -> Result<(), ConfigError> {
        // 验证主数据源配置
        if config.primary.source_type.is_empty() {
            return Err(ConfigError::InvalidConfig(
                "Primary source type cannot be empty".to_string()
            ));
        }

        // 验证备用数据源配置
        for (i, backup) in config.backups.iter().enumerate() {
            if backup.source_type.is_empty() {
                return Err(ConfigError::InvalidConfig(
                    format!("Backup source {} type cannot be empty", i)
                ));
            }
        }

        // 验证超时和重试配置
        if config.primary.connection_timeout == 0 {
            return Err(ConfigError::InvalidConfig(
                "Connection timeout cannot be zero".to_string()
            ));
        }

        if config.switch_back_delay == 0 {
            return Err(ConfigError::InvalidConfig(
                "Switch back delay cannot be zero".to_string()
            ));
        }

        Ok(())
    }

    pub async fn get_current_config(&self) -> MultiDataSourceConfig {
        self.current_config.read().await.clone()
    }

    pub async fn get_health_status(&self) -> Vec<(String, bool)> {
        let checkers = self.health_checkers.read().await;
        let mut status = Vec::new();

        for checker in checkers.iter() {
            status.push((
                checker.get_source_name().to_string(),
                checker.is_healthy().await
            ));
        }

        status
    }

    pub async fn get_performance_metrics(&self) -> Vec<(String, PerformanceMetrics)> {
        let checkers = self.health_checkers.read().await;
        let mut metrics = Vec::new();

        for checker in checkers.iter() {
            metrics.push((
                checker.get_source_name().to_string(),
                checker.get_performance_metrics().await
            ));
        }

        metrics
    }
}